#include "au_edu_adelaide_adept_sdk_java_AdeptSDKJava.h"
#define	_CRT_SECURE_NO_WARNINGS

/* ------------------------------------------------------------ */
/*					Include File Definitions					*/
/* ------------------------------------------------------------ */

#if defined(WIN32)

/* Include Windows specific headers here.
 */
#include <windows.h>

#else

/* Include Unix specific headers here.
 */

#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "dpcdecl.h"
#include "depp.h"
#include "dmgr.h"

/*
 * Class:     AdeptSDKJava
 * Method:    allocateHIF
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_allocateHIF(JNIEnv * env, jobject obj){
	return (long long)malloc(sizeof(HIF));
}

/*
 * Class:     AdeptSDKJava
 * Method:    deallocateHIF
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_deallocateHIF(JNIEnv * env, jobject obj, jlong hifPointer){
	HIF * hif = (HIF*)hifPointer;
	free(hif);
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    allocateDVC
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_allocateDVC(JNIEnv * env, jobject obj){
	return (long long)malloc(sizeof(DVC));
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    deallocateDVC
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_deallocateDVC(JNIEnv * env, jobject obj, jlong dvcPointer){
	DVC * dvc = (DVC*)dvcPointer;
	free(dvc);
}



typedef struct JHIF{
	char disposed;
	HIF * hif;
} JHIF;

void getJHIF(JHIF * jhif, JNIEnv * env, jobject hif ){
	jclass hifClass = env->FindClass("au/edu/adelaide/adept_sdk_java/AdeptSDKJava$HIF");
	jfieldID disposed_id = env->GetFieldID(hifClass, "disposed", "Z");
	jfieldID handlePointer_id = env->GetFieldID(hifClass, "handlePointer", "J");
	jhif->hif = (HIF*)(env->GetLongField(hif, handlePointer_id));
	jhif->disposed = env->GetBooleanField(hif, disposed_id);

}

typedef struct JDVC{
	char disposed;
	DVC * dvc;
} JDVC;

void getJDVC(JDVC * jdvc, JNIEnv * env, jobject dvc ){
	jclass dvcClass = env->FindClass("au/edu/adelaide/adept_sdk_java/AdeptSDKJava$DVC");
	jfieldID disposed_id = env->GetFieldID(dvcClass, "disposed", "Z");
	jfieldID handlePointer_id = env->GetFieldID(dvcClass, "handlePointer", "J");
	jdvc->dvc = (DVC*)(env->GetLongField(dvc, handlePointer_id));
	jdvc->disposed = env->GetBooleanField(dvc, disposed_id);

}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    getDVCszName
 * Signature: (J)V
 */
JNIEXPORT jstring JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_getDVCszName(JNIEnv * env, jobject obj , jobject dvc){
	static JDVC jdvc;
	getJDVC(&jdvc, env, dvc);
	if(jdvc.disposed == 0){
		return env->NewStringUTF(jdvc.dvc->szName);
	}
	return NULL;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    getDVCszConn
 * Signature: (J)V
 */
JNIEXPORT jstring JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_getDVCszConn(JNIEnv * env, jobject obj , jobject dvc){
	static JDVC jdvc;
	getJDVC(&jdvc, env, dvc);
	if(jdvc.disposed == 0){
		return env->NewStringUTF(jdvc.dvc->szConn);
	}
	return NULL;
}

/*
 * Class:     AdeptSDKJava
 * Method:    DmgrOpen
 * Signature: (LAdeptSDKJava/HIF;Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrOpen(JNIEnv * env, jobject object, jobject hif, jstring boardName){
	static JHIF jhif;
	getJHIF(&jhif, env, hif );
	const char * nativeString = env->GetStringUTFChars(boardName, 0);
	char result = 0;
	if(jhif.disposed == 0){
		result = DmgrOpen(jhif.hif, (char*)nativeString);
	}
	env->ReleaseStringUTFChars(boardName, nativeString);
	return result;
}

/*
 * Class:     AdeptSDKJava
 * Method:    DmgrClose
 * Signature: (LAdeptSDKJava/HIF;)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrClose(JNIEnv * env, jobject obj, jobject hif){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed == 0){
		return DmgrClose(*(jhif.hif));
	}
	return 0;
}

/*
 * Class:     AdeptSDKJava
 * Method:    DmgrGetLastError
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrGetLastError(JNIEnv * env, jobject obj){
	return (jint)DmgrGetLastError();
}


/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DmgrEnumDevices
 * Signature: ()I
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrEnumDevices(JNIEnv * env, jobject obj, jintArray pcdvc){
	jint * body = env->GetIntArrayElements(pcdvc, 0);
	jboolean result =  DmgrEnumDevices((int *)body);
	env->ReleaseIntArrayElements(pcdvc, body, 0);
	return result;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DmgrGetDvc
 * Signature: (J)V
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrGetDvc(JNIEnv * env, jobject obj, jint idvc, jobject dvc){
	static JDVC jdvc;
	getJDVC(&jdvc, env, dvc);
	if(jdvc.disposed == 0){
		return DmgrGetDvc(idvc, jdvc.dvc);
	}
	return 0;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DmgrFreeDvcEnum
 * Signature: ()V
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DmgrFreeDvcEnum(JNIEnv * env, jobject obj){
	return DmgrFreeDvcEnum();
}

/*
 * Class:     AdeptSDKJava
 * Method:    DeppEnable
 * Signature: (LAdeptSDKJava/HIF;)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppEnable(JNIEnv * env, jobject obj, jobject hif){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed == 0){
		return DeppEnable(*(jhif.hif));
	}
	return 0;
}

/*
 * Class:     AdeptSDKJava
 * Method:    DeppDisable
 * Signature: (LAdeptSDKJava/HIF;)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppDisable(JNIEnv * env, jobject obj, jobject hif){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed == 0){
		return DeppDisable(*(jhif.hif));
	}
	return 0;
}

/*
 * Class:     AdeptSDKJava
 * Method:    DeppPutReg
 * Signature: (LAdeptSDKJava/HIF;BBZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppPutReg(JNIEnv * env, jobject obj, jobject hif, jbyte address, jbyte data, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed == 0){
		unsigned char a = (unsigned char)address;
		unsigned char d = (unsigned char)data;
		return DeppPutReg(*(jhif.hif), a, d, fFalse);
	}
	return 0;
}


/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DeppGetReg
 * Signature: (Lau/edu/adelaide/adept_sdk_java/AdeptSDKJava/HIF;B[BZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppGetReg
(JNIEnv * env, jobject obj, jobject hif, jbyte address, jbyteArray arr, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed == 0){
		jbyte *body = env->GetByteArrayElements(arr, 0);
		char result = DeppGetReg(*(jhif.hif), (unsigned char) address, (unsigned char *)body, fFalse);
		env->ReleaseByteArrayElements(arr, body, 0);
		return result;
	}
	return 0;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DeppPutRegSet
 * Signature: (Lau/edu/adelaide/adept_sdk_java/AdeptSDKJava/HIF;[BIZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppPutRegSet
(JNIEnv * env, jobject obj, jobject hif, jbyteArray addressDataPair, jint numberOfPairs, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed != 0){
		return 0;
	}
	jbyte *body = env->GetByteArrayElements(addressDataPair, 0);
	char result = DeppPutRegSet(*(jhif.hif), (unsigned char *) body, numberOfPairs, overlap);
	env->ReleaseByteArrayElements(addressDataPair, body, 0);
	return result;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DeppGetRegSet
 * Signature: (Lau/edu/adelaide/adept_sdk_java/AdeptSDKJava/HIF;[B[BIZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppGetRegSet
(JNIEnv * env, jobject obj, jobject hif, jbyteArray addresses, jbyteArray dataArr, jint numberOfReads, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed != 0){
		return 0;
	}
	jbyte *bodyA = env->GetByteArrayElements(addresses, 0);
	jbyte *bodyD = env->GetByteArrayElements(dataArr, 0);
	char result = DeppGetRegSet(*(jhif.hif), (unsigned char *)bodyA, (unsigned char *)bodyD, numberOfReads, overlap);
	env->ReleaseByteArrayElements(addresses, bodyA, 0);
	env->ReleaseByteArrayElements(dataArr, bodyD, 0);
	return result;
}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DeppPutRegRepeat
 * Signature: (Lau/edu/adelaide/adept_sdk_java/AdeptSDKJava/HIF;B[BIZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppPutRegRepeat
(JNIEnv * env, jobject obj, jobject hif, jbyte address, jbyteArray data, jint size, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed != 0){
		return 0;
	}
	jbyte *body = env->GetByteArrayElements(data, 0);
	char result = DeppPutRegRepeat(*(jhif.hif), (unsigned char)address, (unsigned char *) body, size, overlap);
	env->ReleaseByteArrayElements(data, body, 0);
	return result;

}

/*
 * Class:     au_edu_adelaide_adept_sdk_java_AdeptSDKJava
 * Method:    DeppGetRegRepeat
 * Signature: (Lau/edu/adelaide/adept_sdk_java/AdeptSDKJava/HIF;B[BIZ)Z
 */
JNIEXPORT jboolean JNICALL Java_au_edu_adelaide_adept_1sdk_1java_AdeptSDKJava_DeppGetRegRepeat
(JNIEnv * env, jobject obj, jobject hif, jbyte address, jbyteArray dataArr, jint size, jboolean overlap){
	static JHIF jhif;
	getJHIF(&jhif, env, hif);
	if(jhif.disposed != 0){
		return 0;
	}
	jbyte *body = env->GetByteArrayElements(dataArr, 0);
	char result = DeppGetRegRepeat(*(jhif.hif), (unsigned char)address, (unsigned char *) body, size, overlap);
	env->ReleaseByteArrayElements(dataArr, body, 0);
	return result;

}


